<template>
  <div>
    <input ref="fileRef" type="file" class="hidden" :accept="props.accept" />
    <button v-if="!props.fileUrl" class="button" @click="handleUpload">
      <slot>
        <NIcon class="cursor-pointer"  size="40">
          <Add />
        </NIcon>
      </slot>
    </button>
    <div v-else class="relative">
      <img class="img" :src="props.fileUrl" />
      <NIcon class="icon cursor-pointer" size="20" @click="handleClose">
        <Close />
      </NIcon>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { Close, Add } from "@vicons/ionicons5";
import { NIcon } from "naive-ui";
import { qiniuUpload } from "~/api/file";

const props = defineProps({
  accept: {
    type: String,
    default: "*",
  },
  fileUrl: {
    type: String,
    default: "",
  },
});
const emit = defineEmits(["uploadDone", "update:file-url"]);
const fileRef = ref();
const dataFile = ref<{ hash: string; url: string }>({
  hash: "",
  url: "",
});
onMounted(() => {
  fileRef.value?.addEventListener("change", pullFiles);
});

function handleUpload() {
  fileRef.value?.click();
}
function changeInput(type: string) {
  fileRef.value.type = type;
}
function handleClose() {
  dataFile.value = {
    hash: "",
    url: "",
  };
  fileRef.value.files = null;
  emit("update:file-url", "");
}

async function pullFiles() {
  const file = fileRef.value?.files[0];
  // 为了解决同一个文件上传的hack做法
  changeInput("text");
  const res = (await qiniuUpload(file)) as { hash: string; url: string };
  if (res) {
    dataFile.value.hash = res.hash;
    dataFile.value.url = res.url;

    emit("uploadDone", toRef(dataFile));
    emit("update:file-url", dataFile.value?.url);
  }
  changeInput("file");
}
</script>

<style scoped lang="scss">
.hidden {
  display: none;
}
.button {
  --tw-border-opacity: 1;
  border-color: rgb(229 231 235 / var(--tw-border-opacity));
  border-style: solid;
  border-width: 1px;
  border-radius: 0.25rem;
  width: 13rem;
  height: 8rem;
}
.relative {
  position: relative;
  .img {
    width: 13rem;
    height: 8rem;
    border-radius: 0.25rem;
    -o-object-fit: contain;
    object-fit: contain;
  }
  .icon {
    position: absolute;
    top: 0.375rem;
    right: 0.375rem;
    --tw-text-opacity: 1;
    color: rgb(255 255 255 / var(--tw-text-opacity));
  }
}
</style>
